home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume5 / retouch < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  9.3 KB

  1. Subject: retouch(1): force changed date
  2. Keywords: touch, sccs, ls
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 5, Issue 4
  7. Submitted by: seismo!s3sun!gould9!joel (Joel West @ CACI)
  8.  
  9. retouch(1) is like touch(1), except it uses the sccs id instead
  10. of the current time.
  11.  
  12. It also contains a nifty subroutine that can be used as the inverse of 
  13. localtime(3) or gmtime(3), to convert a date to the UNIX time format.  
  14. The algorithm is brute force, but deterministic, and involves no
  15. UNIX proprietary source code.
  16.  
  17.     Joel West         (619) 457-9681
  18.     CACI, Inc. Federal, 3344 N. Torrey Pines Ct., La Jolla, CA  92037
  19.     {cbosgd, ihnp4, sdcsvax, ucla-cs} !gould9!joel
  20.     joel%gould9.uucp@NOSC.ARPA
  21.  
  22. #!/bin/sh
  23. # This is a shell archive, meaning:
  24. # 1. Remove everything above the #!/bin/sh line.
  25. # 2. Save the resulting text in a file.
  26. # 3. Execute the file with /bin/sh (not csh) to create the files:
  27. #    README
  28. #    Makefile
  29. #    retouch.c
  30. # This archive created: Tue May 13 21:52:48 1986
  31. export PATH; PATH=/bin:$PATH
  32. echo shar: extracting "'README'" '(1001 characters)'
  33. if test -f 'README'
  34. then
  35.     echo shar: over-writing existing file "'README'"
  36. fi
  37. sed 's/^X//' << \SHAR_EOF > 'README'
  38. Xretouch is a command that can be used to "correct" last changed
  39. Xdates, such as when by 'make' or 'ls -l -t'.  These dates
  40. Xcan be inaccurate after a cp, or uucp, or kermit to create a new
  41. Xcopy of an existing file, or to import it from another system.
  42. X
  43. Xretouch looks for an sccs string of the form
  44. X    @(#) anything at all mm/dd/yy
  45. X    @(#) anything at all yy/mm/dd
  46. Xto get the date.  It is intended for use on source files, and
  47. Xassumes there is no such string if it's not in the top 10 lines.
  48. X
  49. XIt has the following options:
  50. X    -v    verbose
  51. X    -g    assume the date is GMT rather than local time
  52. X    -d date    set the last change date to "date".
  53. X
  54. XIt has defs for BSD and USG, although it's been tested only
  55. Xunder BSD.  It was intended as a one-time hack, and may not
  56. Xbe as clean as it should be, but it has proven versatile and
  57. Xnecessary over the past 6 months.
  58. X
  59. XI'd appreciate any suggestions or changes.
  60. X
  61. X    Joel West     CACI, Inc. Federal, La Jolla
  62. X    {cbosgd, ihnp4, sdcsvax, ucla-cs} !gould9!joel
  63. X    joel%gould9.uucp@NOSC.ARPA
  64. SHAR_EOF
  65. if test 1001 -ne "`wc -c 'README'`"
  66. then
  67.     echo shar: error transmitting "'README'" '(should have been 1001 characters)'
  68. fi
  69. echo shar: extracting "'Makefile'" '(50 characters)'
  70. if test -f 'Makefile'
  71. then
  72.     echo shar: over-writing existing file "'Makefile'"
  73. fi
  74. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  75. Xretouch: retouch.c
  76. X    cc -DBSD -o retouch retouch.c
  77. SHAR_EOF
  78. if test 50 -ne "`wc -c 'Makefile'`"
  79. then
  80.     echo shar: error transmitting "'Makefile'" '(should have been 50 characters)'
  81. fi
  82. echo shar: extracting "'retouch.c'" '(6231 characters)'
  83. if test -f 'retouch.c'
  84. then
  85.     echo shar: over-writing existing file "'retouch.c'"
  86. fi
  87. sed 's/^X//' << \SHAR_EOF > 'retouch.c'
  88. X/* @(#) retouch.c 1.0 10/25/85
  89. X*/
  90. X/* retouch.c: set update time to match SCCS id
  91. X
  92. X   Copyright (c) 1985, Joel West (ihnp4!gould9!joel)
  93. X   License for non-commercial use freely granted as long
  94. X   as this notice is retained.
  95. X
  96. X   The id should be of the form
  97. X        @(#) xxxxxxx 10/23/85
  98. X    or    @(#) xxxxxxx 85/10/23
  99. X   it assumes date is the last non-blank thing on the line
  100. X   and this program will only work between 1970 and 2000, inclusive
  101. X
  102. X   works best if only one id (ignores others) and if id is at the
  103. X   top of the file.
  104. X
  105. X   Does not retouch if not found in first 10 lines; should be
  106. X   an optionable parameter.  A line is a newline or a null,
  107. X   so this just might work on a binary file.
  108. X
  109. X*/
  110. X
  111. X#include <sys/types.h>
  112. Xtypedef struct {
  113. X    time_t actime;
  114. X    time_t modtime;
  115. X} utimbuf;
  116. X
  117. X#include <sys/stat.h>
  118. X#include <errno.h>
  119. X#ifdef BSD
  120. Xextern int errno;
  121. X#endif
  122. X
  123. X#include <stdio.h>
  124. X#define ungetchar(c) ungetc(c,stdin)
  125. X
  126. X#ifdef BSD
  127. X# include <strings.h>
  128. X# include <sys/time.h>
  129. X#else
  130. X# include <string.h>
  131. X# include <time.h>
  132. X#endif
  133. X#ifdef USG
  134. X# define index(s,c) strchr(s,c)
  135. X#endif
  136. X
  137. X#ifndef TRUE
  138. X# define TRUE (1)
  139. X# define FALSE (0)
  140. X#endif
  141. X
  142. X/* below are hour and minute at local time that should be
  143. X   time-stamped; default 00:00:00.  No user control over seconds  */
  144. X#define STDHR 00
  145. X#define STDMIN 00
  146. X
  147. X#define SCCSKEY "@(#)"
  148. X#define SCCSCHR '@'
  149. X
  150. X#define EOL '\n'
  151. X#define EOS '\0'
  152. X
  153. Xint optg = 0, optd = 0, optv = 0;
  154. Xlong stddate;
  155. X
  156. Xmain(argc,argv)
  157. Xint argc;
  158. Xchar **argv;
  159. X{    int depthlim,line,i,sccslen,touched;
  160. X    char *p,*filenam,buff[1024];
  161. X    int c,errind;
  162. X
  163. X    depthlim = 10;
  164. X    sccslen = strlen(SCCSKEY);
  165. X    errind = 0;
  166. X
  167. X    for (i = 1; i<argc && errind == 0; i++)
  168. X    {   if (*argv[i] != '-')
  169. X        break;
  170. X        p = argv[i];
  171. X        while (*(++p))
  172. X        switch(*p)
  173. X        {    case 'g':
  174. X            optg++;
  175. X            break;
  176. X        case 'v':
  177. X            optv++;
  178. X            break;
  179. X        case 'd':
  180. X            if (optd)
  181. X            errind++;
  182. X            else
  183. X            {   optd++;
  184. X            stddate = dateatol(argv[++i]);
  185. X            if (stddate < 0)
  186. X            {   fprintf(stderr,"%s: invalid date format\n",argv[i]);
  187. X                exit (0);
  188. X            }
  189. X            }
  190. X            break;
  191. X        default:
  192. X            errind++;
  193. X        }
  194. X    }
  195. X
  196. X    if (errind || i >= argc)
  197. X    {   fprintf(stderr, 
  198. X            "usage: %s [-v ] [-g] [-d date] file1 [file2 ... ]\n", 
  199. X            argv[0]);
  200. X        exit (0);
  201. X    }
  202. X
  203. X    for (; i<argc; i++)
  204. X    {   filenam = argv[i];
  205. X        if (freopen(filenam, "r", stdin) == NULL)
  206. X        {    perror(filenam);
  207. X        exit(errno);
  208. X        }
  209. X        touched = 0;
  210. X        if (optd)        /* one date for all */
  211. X        {    setupdtime(filenam, stddate);
  212. X        touched++;
  213. X        goto settouch;
  214. X        }
  215. X        
  216. X        for (line = 1; line <= depthlim; line++)
  217. X        {    while ( 1 )
  218. X        {   c = getchar();
  219. X            if (c == EOF)
  220. X            goto settouch;
  221. X            if (c == EOS || c == EOL)
  222. X            break;
  223. X            if (c == SCCSCHR)
  224. X            {
  225. X            ungetchar(c);
  226. X            gets(buff);        /* won't work on binary */
  227. X            if (strncmp(buff, SCCSKEY, sccslen) == 0)
  228. X            {    p = buff+strlen(buff);    /* use last nonblank */
  229. X                while (*(--p) == ' ')    /* field in string */
  230. X                ;
  231. X                while (*p != ' ' && *p != '\t')
  232. X                --p;
  233. X                if ( setupdtime(filenam, dateatol(++p)) )
  234. X                touched++;
  235. X                goto settouch;
  236. X            }
  237. X            }
  238. X        } /* within line */
  239. X        } /* end of line */
  240. Xsettouch:
  241. X        if (touched==0)
  242. X        fprintf(stderr, "%s: not retouched\n", filenam);
  243. X        else
  244. X        if (optv)
  245. X            fprintf(stderr, "%s: retouched\n", filenam);
  246. X    } /* end of file */
  247. X}
  248. X
  249. X/* Reset the file's update time to the specified date.  If the date is dubious,
  250. X   don't reset it at all
  251. X*/
  252. Xint setupdtime(fname, mtime)
  253. Xchar *fname;
  254. Xlong mtime;
  255. X{    utimbuf timep;
  256. X    struct stat statbuf;
  257. X
  258. X    stat(fname, &statbuf);
  259. X    timep.actime = statbuf.st_atime;    /* copy current accessed time */
  260. X
  261. X    if (mtime > 0)            /* valid date */
  262. X    {   timep.modtime = mtime;
  263. X        utime(fname, &timep);
  264. X        return (TRUE);
  265. X    }
  266. X    return (FALSE);
  267. X}
  268. X
  269. X#define NSECYR 31536000
  270. X/* 365*24*60*60 */
  271. X#define NSECDA 86400
  272. X#define APPROXT(yr,mo,da) (((yr-70)*NSECYR) + ((mo*30)+da)*NSECDA)
  273. X#define INVDATE (-1)
  274. Xlong dateatol(string)
  275. Xchar *string;
  276. X{    char *p,*q;
  277. X    int mdy[3],mo,da,yr,i,num;
  278. X    struct tm *tmptr;
  279. X    long timsec,approxsec,deltasec,lasttimsec,maxdelta,mindelta;
  280. X    int deltasign;
  281. X    static char *numstr = "0123456789";
  282. X
  283. X    p = string;
  284. X    while (*p == ' ')            /* skip leading blanks */
  285. X        p++;
  286. X    for (i = 0 ; i<3; i++)
  287. X    {   num = 0;
  288. X        q = NULL;                /* watch for null field */
  289. X        while (*p != EOS && *p != '/' && *p != ' ')
  290. X        {    q = index(numstr,*p++);
  291. X        if (q == NULL)            /* invalid digit */
  292. X            break;
  293. X        num = num*10 +(q-numstr);
  294. X        }
  295. X        if (q)
  296. X        mdy[i] = num;
  297. X        else
  298. X        return (INVDATE);        /* invalid or null field */
  299. X        p++;    /* skip delimiter */
  300. X    }
  301. X    --p;
  302. X    while (*p++ == ' ')
  303. X        ;
  304. X    if (*--p != EOS)            /* not end of string */
  305. X        return (INVDATE);
  306. X
  307. X    if (mdy[0] > 11)
  308. X    {   yr = mdy[0];        /* assume YY/MM/DD */
  309. X        mo = mdy[1] - 1;        /* months 0..11 not 1..12 */
  310. X        da = mdy[2];
  311. X    }
  312. X    else
  313. X    {   mo = mdy[0] - 1;        /* assume MM/DD/YY */
  314. X        da = mdy[1];
  315. X        yr = mdy[2];
  316. X    }
  317. X    
  318. X    if (yr > 1900)
  319. X        yr = yr - 1900;
  320. X
  321. X    approxsec = APPROXT(yr,mo,da);
  322. X    timsec = approxsec;
  323. X    lasttimsec = 0;
  324. X    mindelta = NSECDA;
  325. X    maxdelta = NSECYR;
  326. X    while (1)
  327. X    {    tmptr = (optg ? gmtime(&timsec) : localtime(&timsec)) ;
  328. X/* decode absolute time into local or gmt */
  329. X         if (yr == tmptr->tm_year && 
  330. X         mo == tmptr->tm_mon &&
  331. X         da == tmptr->tm_mday)
  332. X         {
  333. X/* the date is right, set the time to midnight local time; this 
  334. Xmay behave strangely on daylight savings time changeover days */
  335. X        if (STDHR == tmptr->tm_hour &&
  336. X            STDMIN == tmptr->tm_min &&
  337. X            0 == tmptr->tm_sec)
  338. X            break;            /* exactly right */
  339. X        else
  340. X        {   timsec -= (tmptr->tm_hour - STDHR) * 3600 + 
  341. X                  (tmptr->tm_min - STDMIN) * 60 +
  342. X                   tmptr->tm_sec;
  343. X            maxdelta = mindelta;
  344. X            mindelta = 1;
  345. X        }
  346. X        }
  347. X        else
  348. X        {    deltasec = APPROXT(tmptr->tm_year,tmptr->tm_mon,tmptr->tm_mday)
  349. X               - approxsec;
  350. X        deltasign = (deltasec < 0) ? -1 : 1;
  351. X/* approximately the difference in the number of seconds between 
  352. X   the guessed date and the actual date */
  353. X        if (abs(deltasec) > abs(timsec-lasttimsec))
  354. X            deltasec = timsec-lasttimsec;
  355. X        deltasec = abs(deltasec);
  356. X        deltasec = (deltasec > maxdelta) ? deltasec / 2 :
  357. X            ((deltasec >= mindelta) ? (deltasec-1) : mindelta); 
  358. X        lasttimsec = timsec;
  359. X        timsec -= deltasec * deltasign;    /* binary convergence */
  360. X         }
  361. X    }
  362. X
  363. X    return (timsec);
  364. X}
  365. SHAR_EOF
  366. if test 6231 -ne "`wc -c 'retouch.c'`"
  367. then
  368.     echo shar: error transmitting "'retouch.c'" '(should have been 6231 characters)'
  369. fi
  370. #    End of shell archive
  371. exit 0
  372.  
  373.